"use client";

import { useMemo, useState } from "react";
import type {
  AgentSummary,
  EnvironmentNode,
  EnvironmentView,
  EventRecord,
  GovernanceTask,
  LedgerSnapshot,
  TimelineRecord
} from "@agent-society/types";
import { Panel, MetricCard, TaskColumn, TimelineEntry } from "@agent-society/ui";
import { AgentNetwork } from "./agent-network";
import { TelemetryDeck } from "./telemetry-deck";
import { ExperimentLab } from "./experiment-lab";
import clsx from "clsx";

interface Props {
  agents: AgentSummary[];
  ledger: LedgerSnapshot;
  events: EventRecord[];
  tasks: GovernanceTask[];
  environment?: EnvironmentView;
  timeline?: TimelineRecord[];
}

const TABS = ["Overview", "Network", "Timeline", "Credits", "Tasks", "Environment", "Experiments"] as const;

export function MainVisualization({ agents, ledger, events, tasks, environment, timeline }: Props) {
  const [activeTab, setActiveTab] = useState<(typeof TABS)[number]>("Overview");
  const [focusedTask, setFocusedTask] = useState<string | null>(null);

  const content = useMemo(() => {
    switch (activeTab) {
      case "Overview":
        return (
          <div className="grid gap-4 lg:grid-cols-[2fr_1fr]">
            <MetricCard
              title="Total Credits"
              value={`${ledger.totalCredits.toLocaleString()} cr`}
              description={`Velocity ${ledger.velocity.toFixed(1)} / hr`}
            />
            <Panel title="Issuance vs Charges" description="Last refresh">
              <p className="text-xs text-slate-400">{new Date(ledger.updatedAt).toLocaleTimeString()}</p>
              <div className="mt-3 grid grid-cols-2 gap-3 text-center text-sm">
                <MetricCard title="Issuance" value={ledger.issuance} accent="emerald" />
                <MetricCard title="Charges" value={ledger.charges} accent="rose" />
              </div>
            </Panel>
            <TelemetryDeck events={events} />
          </div>
        );
      case "Network":
        return (
          <Panel title="Agent Collaboration Graph" description="Node size proportional to credit balance">
            <AgentNetwork agents={agents} />
          </Panel>
        );
      case "Timeline":
        if (timeline && timeline.length > 0) {
          return (
            <Panel title="Codex Orchestration Timeline" description="Coordinator decisions and specialist actions">
              <ul className="space-y-3">
                {sortTimeline(timeline).map((entry, index) => (
                  <li key={`${entry.timestamp}-${entry.agent}-${index}`}>
                    <TimelineEntry
                      title={formatTimelineTitle(entry)}
                      subtitle={formatTimelineSubtitle(entry)}
                      timestamp={new Date(entry.timestamp).toLocaleTimeString()}
                      content={renderTimelineContent(entry)}
                      tags={buildTimelineTags(entry, tag => {
                        if (tag.startsWith("task-")) {
                          setFocusedTask(tag);
                          setActiveTab("Tasks");
                        }
                      })}
                      tone={determineTimelineTone(entry)}
                    />
                  </li>
                ))}
              </ul>
            </Panel>
          );
        }
        return (
          <Panel title="Live Event Feed" description="Latest governance and runtime activity">
            <ul className="space-y-3">
              {events.map(event => (
                <li key={event.id}>
                  <TimelineEntry
                    title={event.type.toUpperCase()}
                    subtitle={`${event.actor} → ${event.owner}`}
                    timestamp={new Date(event.createdAt).toLocaleTimeString()}
                    content={<p>{event.content}</p>}
                    tags={Object.keys(event.headers)}
                    tone={event.type === "comment" ? "info" : event.type === "task" ? "warning" : "default"}
                  />
                </li>
              ))}
            </ul>
          </Panel>
        );
      case "Credits":
        return (
          <Panel title="Credit Analytics" description="Aggregated ledger movements">
            <div className="grid gap-3 text-sm text-slate-300">
              <div className="flex items-center justify-between rounded-lg bg-slate-900/30 p-3">
                <span>Net Flow (24h)</span>
                <span className="text-emerald-300">+{(ledger.issuance - ledger.charges).toFixed(1)} cr</span>
              </div>
              <div className="rounded-lg bg-slate-900/30 p-3">
                <p className="text-xs text-slate-400">Ledger heatmap preview</p>
                <LedgerHeatmap total={ledger.totalCredits} issuance={ledger.issuance} charges={ledger.charges} />
              </div>
            </div>
          </Panel>
        );
      case "Tasks":
        return (
          <Panel title="Governance Kanban" description="Task backlog by status">
            <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
              {groupTasks(tasks).map(column => (
                <TaskColumn
                  key={column.status}
                  title={column.status.replace("_", " ")}
                  count={column.items.length}
                  status={column.status}
                >
                  {column.items.map(task => (
                    <div
                      key={task.id}
                      className={clsx(
                        "rounded-lg bg-slate-800/60 p-2 transition",
                        focusedTask === task.id || focusedTask === `task-${task.id}`
                          ? "ring-2 ring-sky-400"
                          : ""
                      )}
                    >
                      <p className="text-sm font-medium text-slate-100">{task.title}</p>
                      <p className="text-xs text-slate-400">{task.assignees.join(", ") || "Unassigned"}</p>
                    </div>
                  ))}
                  {column.items.length === 0 && <p className="text-xs text-slate-500">No tasks</p>}
                </TaskColumn>
              ))}
            </div>
          </Panel>
        );
      case "Experiments":
        return <ExperimentLab />;
      case "Environment":
        return (
          <div className="grid gap-4 lg:grid-cols-[2fr_1fr]">
            <Panel title="Narrative Context" description="Natural language summary shared with Codex orchestrators">
              <pre className="max-h-[320px] overflow-auto rounded-lg bg-slate-950/70 p-4 text-xs leading-relaxed text-slate-300">
                {(environment?.context || "(environment context unavailable)")}
              </pre>
            </Panel>
            <Panel title="Environment Tree" description="Agents, governance, and ledger structure">
              {environment ? (
                <div className="max-h-[320px] overflow-auto pr-2 text-sm">
                  <EnvironmentTree node={environment.tree} />
                </div>
              ) : (
                <p className="text-xs text-slate-500">Environment data not available.</p>
              )}
            </Panel>
          </div>
        );
      default:
        return null;
    }
  }, [activeTab, environment, events, ledger, tasks, timeline, focusedTask]);

  return (
    <div className="flex h-full flex-col gap-4">
      <nav className="surface-panel flex gap-2 rounded-xl p-2 text-sm font-medium text-slate-300">
        {TABS.map(tab => (
          <button
            key={tab}
            type="button"
            onClick={() => setActiveTab(tab)}
            className={clsx(
              "rounded-lg px-3 py-1.5 transition",
              activeTab === tab ? "bg-sky-500/20 text-sky-200" : "hover:bg-slate-800/70"
            )}
          >
            {tab}
          </button>
        ))}
      </nav>
      <div className="flex-1 overflow-auto pr-1">{content}</div>
    </div>
  );
}

function groupTasks(tasks: GovernanceTask[]) {
  const statuses: GovernanceTask["status"][] = ["open", "in_progress", "done", "closed"];
  return statuses.map(status => ({
    status,
    items: tasks.filter(task => task.status === status)
  }));
}

function LedgerHeatmap({ total, issuance, charges }: { total: number; issuance: number; charges: number }) {
  const width = 260;
  const bars = [
    { label: "Total", value: total, color: "#38bdf8" },
    { label: "Issuance", value: issuance, color: "#22d3ee" },
    { label: "Charges", value: charges, color: "#f97316" }
  ];
  const max = Math.max(...bars.map(bar => bar.value), 1);
  return (
    <svg viewBox={`0 0 ${width} ${bars.length * 18 + 6}`} className="w-full">
      {bars.map((bar, index) => (
        <g key={bar.label} transform={`translate(0 ${index * 18})`}>
          <text x={0} y={12} fill="#94a3b8" fontSize={5}>
            {bar.label}
          </text>
          <rect
            x={60}
            y={3}
            width={(bar.value / max) * (width - 70)}
            height={10}
            rx={4}
            fill={bar.color}
            opacity={0.8}
          />
          <text x={width - 4} y={12} textAnchor="end" fill="#e2e8f0" fontSize={5}>
            {bar.value.toFixed(1)}
          </text>
        </g>
      ))}
    </svg>
  );
}

function sortTimeline(entries: TimelineRecord[]) {
  return [...entries].sort(
    (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
  );
}

function formatTimelineTitle(entry: TimelineRecord) {
  const role = entry.role && entry.role !== entry.agent ? ` · ${entry.role}` : "";
  return `${entry.agent}${role}`;
}

function formatTimelineSubtitle(entry: TimelineRecord) {
  const parts: string[] = [];
  if (entry.type) {
    parts.push(entry.type.toUpperCase());
  }
  if (entry.client) {
    parts.push(entry.client);
  }
  if (typeof entry.duration === "number") {
    parts.push(`${entry.duration.toFixed(1)}s`);
  }
  if (typeof entry.returncode === "number" && entry.returncode !== 0) {
    parts.push(`exit ${entry.returncode}`);
  }
  return parts.join(" • ");
}

function renderTimelineContent(entry: TimelineRecord) {
  const text = (entry.output || entry.prompt || "").trim();
  if (!text) {
    return undefined;
  }
  const snippet = text.length > 500 ? `${text.slice(0, 497)}…` : text;
  return <p className="whitespace-pre-wrap text-sm text-slate-200">{snippet}</p>;
}

function buildTimelineTags(entry: TimelineRecord, onTaskClick?: (taskId: string) => void) {
  const tags = new Set<string>();
  if (entry.type) {
    tags.add(entry.type.toLowerCase());
  }
  if (entry.client) {
    tags.add(entry.client);
  }
  if (entry.role && entry.role !== entry.agent) {
    tags.add(entry.role);
  }
  const text = `${entry.output ?? ""} ${entry.prompt ?? ""}`;
  const taskMatches = text.match(/task-[a-z0-9_-]+/gi) || [];
  taskMatches.forEach(tag => tags.add(tag));
  return Array.from(tags).map(tag =>
    onTaskClick && tag.toLowerCase().startsWith("task-")
      ? { label: tag, onClick: () => onTaskClick(tag) }
      : tag
  );
}

function determineTimelineTone(entry: TimelineRecord): "default" | "info" | "warning" | "danger" {
  if (entry.returncode && entry.returncode !== 0) {
    return "danger";
  }
  if ((entry.type || "").toLowerCase() === "system") {
    return "info";
  }
  return "default";
}

function EnvironmentTree({ node }: { node: EnvironmentNode }) {
  return (
    <ul className="space-y-2">
      <EnvironmentTreeNode node={node} depth={0} />
    </ul>
  );
}

function EnvironmentTreeNode({ node, depth }: { node: EnvironmentNode; depth: number }) {
  return (
    <li>
      <div className="rounded-lg border border-slate-800/70 bg-slate-900/60 p-3">
        <div className="flex items-center justify-between gap-2">
          <span className="text-sm font-semibold text-slate-200">{"".padStart(depth * 2, " ")}{node.label}</span>
          {node.tags?.presence ? (
            <span className="rounded-full border border-slate-700/60 px-2 py-0.5 text-xs text-slate-400">
              {node.tags.presence}
            </span>
          ) : null}
        </div>
        {node.description ? <p className="mt-1 text-xs text-slate-400">{node.description}</p> : null}
        {node.tags && Object.keys(node.tags).length > 0 ? (
          <dl className="mt-2 grid grid-cols-2 gap-1 text-[11px] text-slate-500">
            {Object.entries(node.tags)
              .filter(([key]) => key !== "presence")
              .map(([key, value]) => (
                <div key={key} className="flex items-center justify-between gap-2">
                  <dt className="uppercase tracking-wide">{key}</dt>
                  <dd className="text-right text-slate-300">{value}</dd>
                </div>
              ))}
          </dl>
        ) : null}
        {node.children.length > 0 ? (
          <ul className="mt-3 space-y-2">
            {node.children.map(child => (
              <EnvironmentTreeNode key={child.id} node={child} depth={depth + 1} />
            ))}
          </ul>
        ) : null}
      </div>
    </li>
  );
}
